/*
     BibleNotebook - A bible reader software
    Copyright (C) 2014  Williams Fernando Lopez

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
 */

package com.simplebible.ui.components.editors;

import com.hexidec.ekit.Ekit;
import com.hexidec.ekit.EkitCore;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import javax.swing.AbstractAction;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.KeyStroke;
import javax.swing.event.HyperlinkListener;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTMLDocument;
import wl.util.Utils;
import com.simplebible.objects.Preferences;
import wl.ui.SearchPanel;

/**
 *
 * @author Williams Lopez
 */
public class EditorEkit  extends Ekit implements Editor{

    boolean textChange = false;
    AutoSave autoSave;
    File archivo;
    int lastKeyTyped = 0;
    SearchPanel search ;

    public EditorEkit() {
        super(null, null, null, null, true, false, true, true, null, null, true, false, true, true, false);

        
        Utils.propagateBackground(Color.yellow, this.getContentPane(), JScrollPane.class,JPanel.class,JSplitPane.class);
        getCore().setEnterKeyIsBreak(true);
        //Para permitir utilizar los hyperlinks en el Editor
        final EkitCore ec = getCore();

        ec.getTextPane().addKeyListener(new  KeyListener() {
            public void keyTyped(KeyEvent e) {
                setTextChange(true);
                
                try {
                    if (ec.getExtendedHtmlDoc().getText(0, ec.getExtendedHtmlDoc().getLength()).trim().length() == 0) {
                        ec.getExtendedHtmlDoc().insertString(ec.getCaretPosition(), "\u00A0", null);
                        //ec.getHtmlEditorKit().insertHTML(ec.getExtendedHtmlDoc(), ec.getCaretPosition(), "<span>&nbsp;</span>", 0, 0, Tag.SPAN);
                    }
                } catch (Exception ec) {
                }
            }
            public void keyPressed(KeyEvent e) {
                if(e.getKeyCode()==KeyEvent.VK_CONTROL){
                    ec.getTextPane().getCaret().setVisible(false);
                    ec.getTextPane().setEditable(false);
                }

                if((e.getKeyCode()!=KeyEvent.VK_CONTROL) && e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK){
                    ec.getTextPane().getCaret().setVisible(true);
                    ec.getTextPane().setEditable(true);
                }
                
                //Fix espacio
                if ((e.getKeyChar() == KeyEvent.VK_SPACE || e.getKeyChar() == KeyEvent.VK_TAB)) {
                    try {
                        e.consume();
                        String toInsert = "";
                        
                        if (e.getKeyCode() == KeyEvent.VK_SPACE) { 
                            toInsert = "\u00A0";
                        }
                        if (e.getKeyCode() == KeyEvent.VK_TAB) { toInsert = "\u00A0\u00A0\u00A0\u00A0\u00A0"; }

                        HTMLDocument doc = (HTMLDocument) ec.getTextPane().getDocument();
                        doc.insertString(ec.getCaretPosition(), toInsert, null);
                        //ec.getHtmlEditorKit().insertHTML(doc, ec.getCaretPosition(), toInsert, 0, 0,null);


                    } catch (Exception ex) {
                        Utils.printToLog("generic_error", ex, Preferences.LOG_LEVEL_ERROR);
                    }
                }
            }
            public void keyReleased(KeyEvent e) {
                getCore().getTextPane().setEditable(true);
                getCore().getTextPane().getCaret().setVisible(true);
                lastKeyTyped = e.getKeyCode();

                if ((e.getKeyCode() == KeyEvent.VK_SPACE || e.getKeyCode() == KeyEvent.VK_TAB)) {
                    e.consume();
                }
            }
        });

        //INVALIDATING DEFAULT ACTIONS FOR TAB AND SPACE
        AbstractAction doNothing = new AbstractAction("") { public void actionPerformed(ActionEvent e) {} };
        KeyStroke ks_spa=KeyStroke.getKeyStroke(' ');
        KeyStroke ks_tab=KeyStroke.getKeyStroke('\t');
        getCore().getTextPane().getKeymap().addActionForKeyStroke(ks_spa, doNothing);
        getCore().getTextPane().getKeymap().addActionForKeyStroke(ks_tab, doNothing);


        setTextChange(false);
        autoSave = new AutoSave();
        autoSave.start();

        search = new SearchPanel();
        search.setTextComponent(getCore().getTextPane(),getCore().getScrollPane());
        search.setOpaque(false);
    }

    public boolean isTextChange() {
        return textChange;
    }

    public void setTextChange(boolean textChange) {
        this.textChange = textChange;
        getCore().getButtonSave().setEnabled(textChange);        
    }


    @Override
    public void setVisible(boolean v){
        super.setVisible(v);
        getCore().getTextPane().requestFocus();
    }


    public void save() throws Exception {
        try {
            EkitCore ek = this.getCore();
            ek.saveDocument();
        } catch (Exception e) {
            throw e;
        }
    }

    @Override
    public void dispose(){
        this.dispose();
        try {
            save();
        } catch (Exception e) {
            Utils.printToLog("Error al guardar el documento", e, Preferences.LOG_LEVEL_ERROR);
        }
    }

    public void open(File file) throws Exception {

        if(archivo!=null){
            save();
        }

        archivo = file;
        EkitCore ek = this.getCore();
        ek.openDocument(file);
    }
    

    public void addTextOnCursorPosition(String text) {
        try{
            
            int caretPos = getCore().getCaretPosition();
            
            if(caretPos <= 0){
                caretPos = getCore().getTextPane().getDocument().getLength();
            }
            
            getCore().getHtmlEditorKit().insertHTML(
                    (HTMLDocument)this.getCore().getTextPane().getDocument(),
                    caretPos,
                    "<span>" + text + "</span>",
                    0,
                    0,
                    HTML.Tag.SPAN);

           textChange = true;
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void addTextOnDocumentFinal(String text) {
        try{
            String html = this.getCore().getDocumentText();
            int pos = html.lastIndexOf("</body>");
            if(pos <0 ) pos = html.lastIndexOf("</BODY>");
            if(pos <0 ) pos = html.length();


            getCore().getHtmlEditorKit().insertHTML(
                    (HTMLDocument)this.getCore().getTextPane().getDocument(),
                    pos,
                    text,
                    0,
                    0,
                    HTML.Tag.SPAN);

            textChange = true;
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public void addTextOnDocumentStart(String text) {
        try{
            
            getCore().getHtmlEditorKit().insertHTML(
                    (HTMLDocument)this.getCore().getTextPane().getDocument(),
                    0,
                    text,
                    0,
                    0,
                    HTML.Tag.P);

            textChange = true;
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public Container getContentPane() {
        return super.getContentPane();
    }

    @Override
    public void show() {
        super.show();
    }

    public void renameFile(String newFileName) throws Exception{
        if(archivo == null){
            return;
        }

        try{
            File newFile = new File(archivo.getParentFile().getAbsolutePath()+File.separator+newFileName);
            archivo.renameTo(newFile);
            
        }catch(Exception e){
            throw new Exception("Can not rename file. ",e);
        }

    }

    public void requestFocusToText() {
        getCore().getTextPane().requestFocus();
    }

    public boolean isFileOpen() {
        if(archivo!=null){
            return true;
        }else{
            return false;
        }
    }


    class AutoSave extends Thread{

        private boolean run = true;
        private boolean stopAutoSave = false;

        public boolean stopAutoSave(){
            run = false;
            while(!stopAutoSave){
                try {
                    Utils.printToLog("Waiting for stop AutoSave Thread....", null, Preferences.LOG_LEVEL_ERROR);
                    sleep(10);
                } catch (Exception e) {
                }
            }
            return true;
        }

        @Override
        public void run() {
            try {
                while(run){
                    if(isTextChange()){
                        setTextChange(false);
                        save();
                    }
                    Thread.currentThread().sleep(10000);
                }
            } catch (Exception e) {
                Utils.printToLog("Error al guardar los cambios: "+e.getMessage(),e,Preferences.LOG_LEVEL_ERROR);
            }
            stopAutoSave = true;
        }

    }

    public File getOpenFile(){
        return archivo;
    }


    public void addHyperlinkListener(HyperlinkListener l) {
        getCore().getTextPane().addHyperlinkListener(l);
    }







}
